package feeinterface.servlet;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.slf4j.MDC;

import com.ulwx.tool.ArrayUtils;
import com.ulwx.tool.ByteUtils;
import com.ulwx.tool.CTime;
import com.ulwx.tool.CollectionUtils;
import com.ulwx.tool.NetUtils;
import com.ulwx.tool.RequestUtils;
import com.ulwx.tool.StringUtils;
import com.ulwx.type.TObject;

import feeinterface.dao.UserRequestLogDao;
import feeinterface.modeldb.UserRequestLog;
import feeinterface.process.ProcessorManager;
import feeinterface.protocol.req.Exchange;
import feeinterface.protocol.req.ProDownload;
import feeinterface.protocol.req.ProExchange;
import feeinterface.protocol.req.Protocol;
import feeinterface.protocol.utils.Constants;
import feeinterface.utils.URLConfig;

/**
 * 接口servlet
 * 
 * @author huangjingfeng
 * 
 */
public class InterfaceServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static Logger log = Logger.getLogger(InterfaceServlet.class);

	protected void doGet(HttpServletRequest request, HttpServletResponse resp) {
		log.debug("========================================================================================");
		ServletOutputStream out = null;
		long startTime = System.currentTimeMillis();
		String protocolId = "";
		Protocol pro = null;
		String requestURL = "";
		int contentLength = 0;
		RequestUtils ru = null;
		try {

			byte[] result = null;

			try {

				protocolId = request.getParameter("Protocol");
				// downHanderClass = Exchange
				// .getDownLoadHanderClass(Protocol);
				TObject BodyBytes = new TObject(new byte[0]);
				pro = Exchange.geProtocol(protocolId);
				log.debug("1++++++++++++++++Protocol=" + protocolId
						+ ",is download class=" + pro);
				if (pro instanceof ProDownload) { // 为下载协议

					// InitProcessor gp = new InitProcessor();
					Map<String, String[]> reqMap = new HashMap<String, String[]>();
					ProcessorManager.getInstance().process(request, reqMap,
							BodyBytes);
					ru = new RequestUtils(reqMap);
					ru.setObject("HttpResponse", resp);
					ru.setObject("HttpRequest", request);
					protocolId = ru.getString("Protocol");

					String range = "";
					range = request.getParameter("Range");
					if (StringUtils.isEmpty(range)) {
						range = request.getHeader("Range");
					}
					log.debug("3++++++++++++++++range=" + range);
					if (StringUtils.hasText(range)) {
						ru.setString("Range", range);
					}

					if (log.isDebugEnabled()) {
						log.debug("map="
								+ CollectionUtils.toString(ru.getrParms()));

						
						requestURL = request.getRequestURL()
								+ "?"
								+ NetUtils.urlMapToQueryStr(ru.getrParms(),
										"utf-8");
						log.debug("request URL=" + requestURL);
					}

					if (StringUtils.hasText(range)) { // 断点续传

						range = range.trim();
						String regx = "bytes\\s*=\\s*(\\d+)\\s*-\\s*(\\d*)\\s*";
						String[][] strs = StringUtils.searchSubStrByReg(range,
								regx, new int[] { 1, 2 });
						log.debug("4++++++++++++++++range=" + range);
						if (ArrayUtils.isNotEmpty(strs)) {
							String[] str = strs[0];
							resp.setHeader("Accept-Ranges", "bytes");
							// HTTP/1.1 206 Partial Content
							resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);// 206

							// 分析range头
							if (range.contains(",")) {
								range = range.substring(0, range.indexOf(","));
							}
							int start = 0;

							try {
								start = Integer.valueOf(str[0]);
								log.debug("5++++++++++++++++start=" + start);
							} catch (Exception ex2) {
								start = 0;
							}

							if (start == 0) {// 如果是第一次下载
								ru.setBoolean(
										Constants.PROTOCOL_REQ_NEED_STAT_DOWN,
										true);

							} else { // 断点续传下载
								ru.setBoolean(
										Constants.PROTOCOL_REQ_NEED_STAT_DOWN,
										false);
							}
							result = Exchange.gen(ru,
									(byte[]) BodyBytes.getValue());

							int total = result.length;

							if (ArrayUtils.isEmpty(result)) {
								throw new Exception("获得数据失败！");
							}
							int end = 0;
							try {
								end = Integer.valueOf(str[1]);
							} catch (Exception ex2) {
								end = total - 1;
							}
							log.debug("6++++++++++++++++start=" + start
									+ ",end=" + (end + 1) + ",length="
									+ result.length);
							byte[] part = Arrays.copyOfRange(result, start,
									end + 1);
							result = part;
							log.debug("7++++++++++++++++final result="
									+ result.length);
							// // Content-range: bytes 500-999/8000
							resp.setHeader("Content-Range", "bytes " + start
									+ "-" + end + "/" + total);
						} else {
							ru.setBoolean(
									Constants.PROTOCOL_REQ_NEED_STAT_DOWN, true);
							result = Exchange.gen(ru,
									(byte[]) BodyBytes.getValue());
						}

					} else {
						ru.setBoolean(Constants.PROTOCOL_REQ_NEED_STAT_DOWN,
								true);
						result = Exchange
								.gen(ru, (byte[]) BodyBytes.getValue());
					}

				} else {// 非下载协议
					Map<String, String[]> reqMap = new HashMap<String, String[]>();
					ProcessorManager.getInstance().process(request, reqMap,
							BodyBytes);
					ru = new RequestUtils(reqMap);
					ru.setObject("HttpResponse", resp);
					ru.setObject("HttpRequest", request);
					if (log.isDebugEnabled()) {
						log.debug("map="
								+ CollectionUtils.toString(ru.getrParms()));
						requestURL = request.getRequestURL() 
								+ "?"
								+ NetUtils.urlMapToQueryStr(ru.getrParms(),
										"utf-8");
						log.debug("request URL=" + requestURL);
					
					}
				
					protocolId = ru.getString("Protocol");
					Boolean debug = ru.getBoolean("Debug");
					log.debug("debug=" + debug);
					result = Exchange.gen(ru, (byte[]) BodyBytes.getValue());

				}
			} catch (Exception ex) {
				log.error("", ex);
				contentLength = 1;
				//result = "ERROR".getBytes();
				result=new byte[]{0};
				ru.setString(Constants.LogKey.RETURN_RESULT,"0");
			}
			Boolean debug = ru.getBoolean("Debug");
			if(debug!=null && debug){
				resp.setContentType("text/plain;charset=utf-8");
			}else{
			   resp.setContentType("application/octet-stream;charset=utf-8");
			}
			if (ArrayUtils.isNotEmpty(result)) {

				log.debug("+++2final : return size=" + contentLength);
				contentLength = result.length;
				resp.setHeader("Content-Length", contentLength + "");
				// resp.setContentLength(contentLength);
				out = resp.getOutputStream();
				// 如果不是下载协议，是交换协议则
				if (pro instanceof ProExchange) {
					if (log.isDebugEnabled()) {
						//log.debug("HEX=\n" + ByteUtils.format(result));
					}
				}
				out.write(result);

				log.debug("+++3final : return size=" + contentLength);

			} else {
				contentLength = 1;
				resp.setHeader("Content-Length", contentLength + "");
				out.write(new byte[]{0});
				ru.setString(Constants.LogKey.RETURN_RESULT,"0");
				// resp.setContentLength(contentLength);
			}

			log.debug("+++final : return size=" + contentLength);

		} catch (Exception e) {
			log.error("", e);

		} finally {
			if (out != null) {
				try {
					out.flush();
					log.debug("flush done.....");
					out.close();
					log.debug("close done.....");

				} catch (IOException e) {
					log.error("", e);
				}
			}
		}



		if (log.isDebugEnabled()) {
			UserRequestLog urlog = new UserRequestLog();

			urlog.setRequestURL(requestURL + "&Debug=true");
			if (ru != null) {
				String extVar = ru.getString("ExtVar");
				Map<String, String[]> extVarMap = NetUtils
						.urlQueryStrToMap(extVar, "utf-8");
				urlog.setMobileID(ArrayUtils.getFirst(extVarMap
						.get("MobileID")));
				urlog.setServiceCoID(ru.getInt("PacketID"));
				urlog.setPacketID(ru.getString("PacketID"));
				urlog.setProtocol(ru.getString("Protocol"));
				urlog.setReturnSize(contentLength);
				urlog.setUpdateTime(CTime.getCurrentDateTime());
				urlog.setResponseTime(System.currentTimeMillis()
						- startTime);
				urlog.setPhone(ru.getString("Mobile"));
				urlog.setIMSI(ru.getString("IMSI"));
				
				urlog.setLogID(MDC.get("logid"));
				urlog.setReturnContent(ru
						.getString(Constants.LogKey.RETURN_RESULT)==null?"0":ru
								.getString(Constants.LogKey.RETURN_RESULT));
				try{
				  urlog.setCity(ru.getInt(Constants.PROTOCOL_REQ_CITY));
				}catch(Exception ee){
					urlog.setCity(Constants.Area.UNKNOWN_CITYID);
				}
				try{
				   urlog.setProvince(ru.getInt(Constants.PROTOCOL_REQ_PROVINCE));
				}catch(Exception ee){
					urlog.setProvince(Constants.Area.UNKNOWN_PROVINCEID);
				}
				urlog.setServerIP(request.getLocalAddr()+"");
			}
			try {
				UserRequestLogDao.Insert(urlog);
			} catch (Exception e) {
				log.error("", e);
			}

		}

	
		log.debug("====协议号:" + protocolId + "-响应时间："
				+ (System.currentTimeMillis() - startTime) + " 毫秒");

	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		this.doGet(req, resp);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		// String str =
		// "Protocol=006001&PacketID=1000&SoftID=2&OldVersion=0&MobileID=100843&Test=1&Debug=true";
		// Map map = NetUtils.urlQueryStrToMap(str, "utf-8");
		// System.out.println(ObjectUtils.toJsonString(map));
		// System.out.println("reqiest URL=" + URLConfig.ROOT + "?"
		// + NetUtils.urlMapToQueryStr(map));
		// Map<String, String[]> bodyMap = new HashMap<String, String[]>();
		// bodyMap.putAll(map);
		// RequestUtils ru = new RequestUtils(bodyMap);
		// System.out.println(ru.getBoolean("Debug"));

	}
}
